/**
 * fshows.com
 * Copyright (C) 2013-2018 All Rights Reserved.
 */
package com.fshows.leshuapay.sdk.util;

import cn.hutool.core.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentSkipListMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author zhaoyi
 * @version LeshuaUtils.java, v 0.1 2020-07-28 09:47 zhaoyi
 */
@Slf4j
public class LeshuaUtils {

    private static final String XML = "xml";

    private static Pattern UNDERLINE_PATTERN = Pattern.compile("[A-Z]");

    public static byte[] readInput(InputStream in) throws IOException {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int len = 0;
        byte[] buffer = new byte[1024];
        try {
            while ((len = in.read(buffer)) > 0) {
                out.write(buffer, 0, len);
            }
        } finally {
            out.close();
            in.close();
        }
        return out.toByteArray();
    }

    public static String inputStreamToString(InputStream is) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i;
        while ((i = is.read()) != -1) {
            baos.write(i);
        }
        return baos.toString(SignUtil.DEFAULT_CHARSET);
    }


    public static InputStream getStringStream(String sInputString) throws UnsupportedEncodingException {
        ByteArrayInputStream tInputStringStream = null;
        if (sInputString != null && !sInputString.trim().equals(StringPool.EMPTY)) {
            tInputStringStream = new ByteArrayInputStream(sInputString.getBytes(SignUtil.DEFAULT_CHARSET));
        }
        return tInputStringStream;
    }

    public static <Res> Res getObjectFromXML(String xml, Class<Res> tClass, String alias) throws Exception {
        Map<String, String> mapFromXML = getMapFromXML(xml);
        return BeanUtil.toBean(mapFromXML, tClass);

//        //将从API返回的XML数据映射到Java对象
//        XStream xStreamForResponseData = new XStream(new DomDriver(SignUtil.DEFAULT_CHARSET,
//                new UpperCaseNameCoder()));
//        XStream.setupDefaultSecurity(xStreamForResponseData);
//        xStreamForResponseData.alias(alias, tClass);
//        xStreamForResponseData.allowTypes(new Class[]{tClass});
//        //暂时忽略掉一些新增的字段
//        xStreamForResponseData.ignoreUnknownElements();
//        Object object = xStreamForResponseData.fromXML(xml);
//        return JSON.parseObject(JSONObject.toJSONString(object), tClass);
    }
    /**
     * 将对象转换成map，key为属性名，value为属性值，值为null的属性排除
     *
     * @param obj
     * @return
     */
    public static Map<String, String> toMap(Object obj) {
        Map<String, String> map = new ConcurrentSkipListMap<>();
        Field[] fields = obj.getClass().getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                if (Modifier.isStatic(field.getModifiers())) {
                    continue;
                }
                Object val = field.get(obj);
                if (val != null) {
                    String key = field.getName();
                    map.put(camelToUnderline(key), String.valueOf(val));
                }
            } catch (IllegalArgumentException | IllegalAccessException e) {
                log.error(e.getMessage(), e);
            }
        }
        return map;
    }

    /**
     * 计算失效时间
     *
     * @param now
     * @param expireInMinutes
     * @param dateFormat
     * @return
     */
    public static String calcExpireTime(Date now, String expireInMinutes, SimpleDateFormat dateFormat) {
        return dateFormat.format(now.getTime() + Long.parseLong(expireInMinutes) * 60 * 1000);
    }

    /**
     * 驼峰转下划线
     */
    public static String camelToUnderline(String str) {
        Matcher matcher = UNDERLINE_PATTERN.matcher(str);
        StringBuffer sb = new StringBuffer();
        while (matcher.find()) {
            matcher.appendReplacement(sb, "_" + matcher.group(0).toLowerCase());
        }
        matcher.appendTail(sb);
        return sb.toString();
    }

    public static Map<String, String> getMapFromXML(String xmlString)
            throws ParserConfigurationException, IOException, SAXException {
        //xmlString = xmlString.replaceFirst("encoding=\".*\"", "encoding=\"GBK\"");
        // 这里用Dom的方式解析回包的最主要目的是防止API新增回包字段
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        InputStream is = getStringStream(xmlString);
        Document document = builder.parse(is);

        // 获取到document里面的全部结点
        NodeList allNodes = document.getFirstChild().getChildNodes();
        Node node;
        Map<String, String> map = new HashMap<String, String>();
        int i = 0;
        while (i < allNodes.getLength()) {
            node = allNodes.item(i);
            if (node instanceof Element) {
                map.put(node.getNodeName(), node.getTextContent());
            }
            i++;
        }
        return map;

    }
}

